package com.example.starter.config;

import com.google.common.collect.Lists;

import javassist.expr.NewExpr;

import org.apache.http.client.HttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.client.ClientHttpRequestFactory;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.http.converter.ByteArrayHttpMessageConverter;
import org.springframework.http.converter.FormHttpMessageConverter;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.ResourceHttpMessageConverter;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.http.converter.support.AllEncompassingFormHttpMessageConverter;
import org.springframework.http.converter.xml.Jaxb2RootElementHttpMessageConverter;
import org.springframework.http.converter.xml.SourceHttpMessageConverter;
import org.springframework.web.client.ResponseErrorHandler;
import org.springframework.web.client.RestTemplate;

import java.io.IOException;
import java.nio.charset.Charset;
import java.util.List;

@Configuration
public class HttpClientConfiguration {

    @Bean
    public ClientHttpRequestFactory httpRequestFactory() {
        return new HttpComponentsClientHttpRequestFactory(httpClient());
    }

    @Bean
    public RestTemplate restTemplate() {
        RestTemplate restTemplate = new RestTemplate(buildConverter());
        restTemplate.setRequestFactory(httpRequestFactory());
        restTemplate.setErrorHandler(new SilentResponseErrorHandler());
        return restTemplate;
    }

    private List<HttpMessageConverter<?>> buildConverter() {
        return Lists.newArrayList(new ByteArrayHttpMessageConverter(),
                                  new StringHttpMessageConverter(Charset.forName("UTF-8")),
                                  new ResourceHttpMessageConverter(),
                                  new SourceHttpMessageConverter<>(),
                                  new AllEncompassingFormHttpMessageConverter(),
                                  new Jaxb2RootElementHttpMessageConverter(),
                                  new MappingJackson2HttpMessageConverter(),
                                  new FormHttpMessageConverter());
    }

    @Bean
    public HttpClient httpClient() {
        PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager();
        connectionManager.setMaxTotal(400);
        connectionManager.setDefaultMaxPerRoute(200);
        return HttpClientBuilder
                .create()
                .setConnectionManager(connectionManager)
                .build();
    }

    private class SilentResponseErrorHandler implements ResponseErrorHandler {
        @Override
        public boolean hasError(ClientHttpResponse response) throws IOException {
            return false;
        }

        @Override
        public void handleError(ClientHttpResponse response) throws IOException {

        }
    }
}
